
use serde::{Serialize, Deserialize};
use std::time::{SystemTime, UNIX_EPOCH};
use jsonwebtoken::errors::ErrorKind;
use jsonwebtoken::{encode, decode, Header, EncodingKey, Validation, DecodingKey, TokenData};
use std::borrow::Borrow;
use std::ptr::null;


/// Our claims struct, it needs to derive `Serialize` and/or `Deserialize`
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,
    exp: u64,
    email: String
}
const HOUR: u64 = 60*60;

const SECRET:&[u8] = b"dwb.ren";


pub struct UtilJwt {}
impl UtilJwt
{
    pub fn gen_token(email: String) -> String {

        let exp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 3 * HOUR;
        let my_claims = Claims {
            sub: "b@b.com".to_string(),
            exp,
            email
        };

        // my_claims is a struct that implements Serialize
        // This will create a JWT using HS256 as algorithm
        encode(&Header::default(), &my_claims, &EncodingKey::from_secret(SECRET)).unwrap()
    }

    pub fn valid_token(token: String) -> (bool, String)
    {
        let validation = Validation { sub: Some("b@b.com2".to_string()), ..Validation::default() };
        match decode::<Claims>(&token, &DecodingKey::from_secret(SECRET), &validation) {
            Ok(c) => (true, "".to_string()),
            Err(err) => match *err.kind() {
                ErrorKind::InvalidToken => (false, "Token is invalid".to_string()), // Example on how to handle a specific error
                ErrorKind::InvalidIssuer => (false, "Issuer is invalid".to_string()), // Example on how to handle a specific error
                _ => (false, "Some other errors".to_string()),
            },
        }
    }
}

#[test]
fn test_jwt() {
    let token = UtilJwt::gen_token("ac@dwb.ren".to_string());
    println!("gen token is ->{:?}", token);
    let info = UtilJwt::valid_token(token);
    println!("valid token is ->{:?}", info);}